home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Texteditors / Origami / Sources / src / origami / display.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-27  |  42.5 KB  |  1,700 lines

  1. /*{{{}}}*/
  2. /*{{{  includes*/
  3. #ifdef CONFIG_H
  4. #   include "config.h"
  5. #endif
  6.  
  7. #include <sys/types.h>
  8. #include <limits.h>
  9. #include <signal.h>
  10. #include <string.h>
  11. #include <stdlib.h>
  12. #include <stdio.h>
  13.  
  14. #define DISPLAY_C
  15. #define I_BUFFLOOP_C
  16. #define I_FIELDEDIT_C
  17. #define I_FINDS_C
  18. #define I_FOLDHELP_C
  19. #define I_FOLDING_C
  20. #define I_GETTK_C
  21. #define I_GETMSG_C
  22. #define I_KEYBOARD_C
  23. #define I_LOOP_C
  24. #define I_MISC_C
  25. #define I_MESSAGES_C
  26. #define I_ORIEDT_C
  27. #define I_PROMPT_C
  28. #define I_SCREEN_C
  29. #define I_SHELL_C
  30. #define I_SIGNALS_C
  31. #define I_VIRTUAL_C
  32.  
  33. #include "origami.h"
  34. #include <lib/ori_add_lib.h>
  35. #include <h/envvar_str.h>
  36. /*}}}  */
  37.  
  38. /*{{{  variables*/
  39. public unsigned char *u_modes[MODE_COUNT*2];
  40. public boolean um_active[MODE_COUNT];
  41. public int n_modes[MODE_COUNT];
  42. public unsigned char print_buffer[BUFFERLEN+1];
  43. public int area_used=0;
  44. public win_data area_line;
  45. public int message_line;
  46. public dsp_data dsp=
  47.  { 8,        /* tab size: default is standard width 8 */
  48.    hex_dsp,  /* base: base for number-display */
  49.    mark_dsp, /* ctrl: marked display */
  50.    norm_dsp, /* norm: ascii output for normal chars */
  51.    norm_dsp, /* tilde: as normal char */
  52.    norm_dsp, /* high: -bit as ascii */
  53.    0,        /* ctrl_add: 0 -> marked display ^A */
  54.  };
  55. public boolean dirty;
  56. public unsigned char *w_name=0;
  57. public boolean xy_show=False;
  58. public boolean allow_text_so=True;
  59. private unsigned char **area_lines=0;
  60. private boolean highlighted;
  61. /*}}}  */
  62.  
  63. /*{{{  on_screen*/
  64. public int on_screen(element const * const p)
  65. {
  66.   element *q;
  67.   int line;
  68.  
  69.   for (q=bd.scr.start,line=0;;)
  70.    { if (++line>bd.scr.txt_size.h)
  71.         break;
  72.      else if (p==q)
  73.         return(line);
  74.      else if (q==bd.scr.end)
  75.         break;
  76.      else
  77.         q=q->next;
  78.    }
  79.   return(0);
  80. }
  81. /*}}}  */
  82. /*{{{  chg_dsp_type*/
  83. public void chg_dsp_type(int code)
  84.  {
  85.    if (code<=0)
  86.     { dsp.tab_size= -code;
  87.       if (dsp.tab_size>LINELEN/8)
  88.          dsp.tab_size=0;
  89.     }
  90.    else
  91.       switch (code)
  92.        {
  93.          /*{{{  switch bases*/
  94.          case 'o':
  95.             dsp.base=oct_dsp;
  96.             goto switch_base;
  97.          case 'd':
  98.             dsp.base=dec_dsp;
  99.             goto switch_base;
  100.          case 'h':
  101.             dsp.base=hex_dsp;
  102.          switch_base:
  103.             if (numb_dsp(dsp.ctrl))
  104.                dsp.ctrl=dsp.base;
  105.             if (numb_dsp(dsp.norm))
  106.                dsp.norm=dsp.base;
  107.             if (numb_dsp(dsp.tilde))
  108.                dsp.tilde=dsp.base;
  109.             if (numb_dsp(dsp.high))
  110.                dsp.high=dsp.base;
  111.             break;
  112.          /*}}}  */
  113.          /*{{{  control handling*/
  114.          case 'm':
  115.             dsp.ctrl=mark_dsp;
  116.             dsp.ctrl_add=0;
  117.             break;
  118.          case 'i':
  119.             if (allow_text_so)
  120.              { dsp.ctrl=ictrl_dsp;
  121.                dsp.ctrl_add= -1;
  122.              }
  123.             break;
  124.          case 'n':
  125.             dsp.ctrl=dsp.base;
  126.             dsp.ctrl_add= -1;
  127.             break;
  128.          /*}}}  */
  129.          /*{{{  number select*/
  130.          case 'p':
  131.             dsp.norm=dsp.tilde=dsp.high=norm_dsp;
  132.          case '8':
  133.             dsp.norm=dsp.tilde=norm_dsp;
  134.             dsp.high=dsp.base;
  135.             break;
  136.          case 'a':
  137.             dsp.ctrl=dsp.norm=dsp.tilde=dsp.high=dsp.base;
  138.             break;
  139.          /*}}}  */
  140.          default:
  141.             break;
  142.        }
  143.    if (hz)
  144.       dsp.tilde=dsp.ctrl;
  145.    /*{{{  check missing features*/
  146.    if (!eight_bits && dsp.high==norm_dsp)
  147.       dsp.high=dsp.base;
  148.    if (!allow_text_so && dsp.ctrl==ictrl_dsp)
  149.     { dsp.ctrl=mark_dsp;
  150.       dsp.ctrl_add=0;
  151.     }
  152.    /*}}}  */
  153.    set_fold_mark_dsp_length(&(init_buffer.f.str));
  154.  }
  155. /*}}}  */
  156. /*{{{  char_dsp_size*/
  157. enum dsp_size char_dsp_size(unsigned char const c)
  158.  {
  159.    if (c==(unsigned char)'~')
  160.       return(dsp.tilde);
  161.    if ((unsigned int)c<(unsigned int)' ')
  162.       if (c==(unsigned char)'\t' && dsp.tab_size && !numb_dsp(dsp.norm))
  163.          return(tab_dsp);
  164.       else
  165.          return(dsp.ctrl);
  166.    if ((unsigned int)c<(unsigned int)127)
  167.       return(dsp.norm);
  168.    else if (c==(unsigned char)127)
  169.       return(dsp.ctrl);
  170.    return(dsp.high);
  171.  }
  172. /*}}}  */
  173. /*{{{  txt2scr*/
  174. public int txt2scr(int offset,int x,unsigned char const *s)
  175. { int i;
  176.  
  177.   for (i=1,s--;x;x--)
  178.    { unsigned char c;
  179.  
  180.      switch ((c= *++s))
  181.       { case '\0':
  182.          /*{{{  string empty, add the missing moves and break from loop*/
  183.            i+=x;
  184.            break;
  185.          /*}}}  */
  186.         /*{{{  case [ a-zA-Z0-9]*/
  187.         case ' ':
  188.         case '0':
  189.         case '1':
  190.         case '2':
  191.         case '3':
  192.         case '4':
  193.         case '5':
  194.         case '6':
  195.         case '7':
  196.         case '8':
  197.         case '9':
  198.         case 'A':
  199.         case 'B':
  200.         case 'C':
  201.         case 'D':
  202.         case 'E':
  203.         case 'F':
  204.         case 'G':
  205.         case 'H':
  206.         case 'I':
  207.         case 'J':
  208.         case 'K':
  209.         case 'L':
  210.         case 'M':
  211.         case 'N':
  212.         case 'O':
  213.         case 'P':
  214.         case 'Q':
  215.         case 'R':
  216.         case 'S':
  217.         case 'T':
  218.         case 'U':
  219.         case 'V':
  220.         case 'W':
  221.         case 'X':
  222.         case 'Y':
  223.         case 'Z':
  224.         case 'a':
  225.         case 'b':
  226.         case 'c':
  227.         case 'd':
  228.         case 'e':
  229.         case 'f':
  230.         case 'g':
  231.         case 'h':
  232.         case 'i':
  233.         case 'j':
  234.         case 'k':
  235.         case 'l':
  236.         case 'm':
  237.         case 'n':
  238.         case 'o':
  239.         case 'p':
  240.         case 'q':
  241.         case 'r':
  242.         case 's':
  243.         case 't':
  244.         case 'u':
  245.         case 'v':
  246.         case 'w':
  247.         case 'x':
  248.         case 'y':
  249.         case 'z':
  250.         /*}}}  */
  251.          /*{{{  handle some norm here*/
  252.            i+=dsp.norm;
  253.            continue;
  254.          /*}}}  */
  255.         default:
  256.          /*{{{  add number of needed chars*/
  257.          { enum dsp_size lg;
  258.  
  259.            switch ((lg=CHAR_DSP_SIZE(c)))
  260.             { case tab_dsp:
  261.                  i=((offset+i+dsp.tab_size-1)/dsp.tab_size)*dsp.tab_size-offset+1;
  262.                  break;
  263.               case ictrl_dsp:
  264.                  lg=1;
  265.               default:
  266.                  i+=lg;
  267.                  break;
  268.             }
  269.            continue;
  270.          }
  271.          /*}}}  */
  272.       }
  273.      break;
  274.    }
  275.   return(i);
  276. }
  277. /*}}}  */
  278. /*{{{  scr2txt*/
  279. public int scr2txt(int offset,int x,unsigned char const *s)
  280. { int i,is;
  281.  
  282.   for (is=1,i=0,s-=1;is<x;i++)
  283.    { unsigned char c;
  284.  
  285.      switch ((c= *++s))
  286.       { case '\0':
  287.          /*{{{  string empty, add missing moves and break from loop*/
  288.            i+=(x-is)/dsp.norm;
  289.            break;
  290.          /*}}}  */
  291.         /*{{{  case [ a-zA-Z0-9]*/
  292.         case ' ':
  293.         case '0':
  294.         case '1':
  295.         case '2':
  296.         case '3':
  297.         case '4':
  298.         case '5':
  299.         case '6':
  300.         case '7':
  301.         case '8':
  302.         case '9':
  303.         case 'A':
  304.         case 'B':
  305.         case 'C':
  306.         case 'D':
  307.         case 'E':
  308.         case 'F':
  309.         case 'G':
  310.         case 'H':
  311.         case 'I':
  312.         case 'J':
  313.         case 'K':
  314.         case 'L':
  315.         case 'M':
  316.         case 'N':
  317.         case 'O':
  318.         case 'P':
  319.         case 'Q':
  320.         case 'R':
  321.         case 'S':
  322.         case 'T':
  323.         case 'U':
  324.         case 'V':
  325.         case 'W':
  326.         case 'X':
  327.         case 'Y':
  328.         case 'Z':
  329.         case 'a':
  330.         case 'b':
  331.         case 'c':
  332.         case 'd':
  333.         case 'e':
  334.         case 'f':
  335.         case 'g':
  336.         case 'h':
  337.         case 'i':
  338.         case 'j':
  339.         case 'k':
  340.         case 'l':
  341.         case 'm':
  342.         case 'n':
  343.         case 'o':
  344.         case 'p':
  345.         case 'q':
  346.         case 'r':
  347.         case 's':
  348.         case 't':
  349.         case 'u':
  350.         case 'v':
  351.         case 'w':
  352.         case 'x':
  353.         case 'y':
  354.         case 'z':
  355.         /*}}}  */
  356.          /*{{{  handle some norm here*/
  357.            is+=dsp.norm;
  358.            continue;
  359.          /*}}}  */
  360.         default:
  361.          /*{{{  handle display length*/
  362.          { enum dsp_size lg;
  363.  
  364.            switch ((lg=CHAR_DSP_SIZE(c)))
  365.             { case tab_dsp:
  366.                  is=((offset+is+dsp.tab_size-1)/dsp.tab_size)*dsp.tab_size-offset+1;
  367.                  break;
  368.               case ictrl_dsp:
  369.                  lg=1;
  370.               default:
  371.                  is+=lg;
  372.                  break;
  373.             }
  374.            continue;
  375.          }
  376.          /*}}}  */
  377.       }
  378.      break;
  379.    }
  380.   return(i);
  381. }
  382. /*}}}  */
  383. /*{{{  x_shift*/
  384. public void  x_shift
  385.  ( int * const p_off,
  386.    int * const p_txt,
  387.    int old,
  388.    int po,
  389.    int off,
  390.    unsigned char const *t
  391.  )
  392. {
  393.   int s;
  394.   int v_txt;
  395.  
  396.   while (po<=old+(soln_str?1:0))
  397.      old-=bd.scr.shift_size;
  398.   for
  399.    ( s=0,v_txt=0
  400.    ; po>=bd.scr.txt_size.w
  401.      || old>=bd.scr.shift_size
  402.    ;
  403.    )
  404.    /*{{{  do a shift (width is bd.scr.shift_size)*/
  405.    { int x;
  406.  
  407.      for (x=bd.scr.shift_size;x>0;)
  408.       { unsigned char c;
  409.  
  410.         if (!(c = *t))
  411.          /*{{{  ready, so break from loop*/
  412.          { s+=x;
  413.            x=0;
  414.            break;
  415.          }
  416.          /*}}}  */
  417.         else
  418.          /*{{{  handle length of display*/
  419.          { enum dsp_size lg;
  420.  
  421.            switch ((lg=CHAR_DSP_SIZE(c)))
  422.             { case tab_dsp:
  423.                  do { s++;x--; } while ((off+s)%dsp.tab_size);
  424.                  break;
  425.               case ictrl_dsp:
  426.                  lg=1;
  427.               default:
  428.                  s+=lg;
  429.                  x-=lg;
  430.                  break;
  431.             }
  432.            t++;
  433.            v_txt++;
  434.          }
  435.          /*}}}  */
  436.       }
  437.      old-=bd.scr.shift_size-x;
  438.      po-=bd.scr.shift_size-x;
  439.    }
  440.    /*}}}  */
  441.   *p_off=s;
  442.   *p_txt=v_txt;
  443. }
  444. /*}}}  */
  445. /*{{{  invers*/
  446. #define invers() (highlighted?do_standend():do_standout())
  447. /*}}}  */
  448. /*{{{  noinvers*/
  449. #define noinvers() (highlighted?do_standout():do_standend())
  450. /*}}}  */
  451. /*{{{  prtendwin*/
  452. private void prtendwin(unsigned char const c)
  453. {
  454.   if (!bd.scr.clreol && !var_notitle)
  455.      if (allow_text_so)
  456.       { invers();
  457.         oputc(c);
  458.         noinvers();
  459.       }
  460.      else
  461.         oputc(c!=' '?c:'|');
  462.   else
  463.      oputc(c);
  464.   }
  465. /*}}}  */
  466. /*{{{  clrbuffline*/
  467. public void clrbuffline(int y,int x)
  468. {
  469.   y+=bd.scr.off.h;
  470.   if (bd.scr.clreol)
  471.      moveclreol(y,x+bd.scr.off.w);
  472.   else
  473.    { int l;
  474.  
  475.      move_cursor_to(y,x+bd.scr.off.w);
  476.      for (l=bd.scr.win.w-x;l--;) oputc(' ');
  477.      prtendwin(' ');
  478.    }
  479. }
  480. /*}}}  */
  481. /*{{{  highlight*/
  482. private void highlight(boolean on,boolean title)
  483. {
  484.   if (!allow_text_so && !title) return;
  485.   if (on) on=True;
  486.   if (highlighted!=on)
  487.    { highlighted=on;
  488.      if (highlighted) do_standout(); else do_standend();
  489.    }
  490. }
  491. /*}}}  */
  492. /*{{{  prt_highlight_bin_text*/
  493. /*{{{  chg_highlight_type*/
  494. private int chg_highlight_type(int limit,int m2)
  495. {
  496.   if (limit==m2)
  497.    { highlight(False,False);
  498.      limit=bd.scr.txt_size.w+2;
  499.    }
  500.   else
  501.    { highlight(True,False);
  502.      limit=m2;
  503.    }
  504.  
  505.   return(limit);
  506. }
  507. /*}}}  */
  508.  
  509. public int prt_highlight_bin_text
  510.  ( int m1,
  511.    int m2,
  512.    int off,
  513.    int len,
  514.    boolean mark,
  515.    unsigned char *s
  516.  )
  517. { unsigned char *s1,*s2;
  518.   unsigned char c;
  519.   int x;
  520.   int limit;
  521.  
  522.   /*{{{  set limit for highlight switch*/
  523.   limit=m1;
  524.   if (m1<=0)
  525.      limit=chg_highlight_type(m1,m2);
  526.   if (m2<=0)
  527.      limit=chg_highlight_type(m2,m2);
  528.   /*}}}  */
  529.   for (s1=s2=s,x=0;(c = *s2) && len;)
  530.    /*{{{  search special char and print leading text followed by special*/
  531.    {
  532.      if (x==limit)
  533.       /*{{{  prt old part and change highlight type*/
  534.       { *s2='\0';
  535.         oputs(s1);
  536.         *(s1=s2)=c;
  537.         limit=chg_highlight_type(limit,m2);
  538.       }
  539.       /*}}}  */
  540.      { enum dsp_size lg;
  541.  
  542.        if ((lg=CHAR_DSP_SIZE(c))==norm_dsp)
  543.         /*{{{  scan over normal text*/
  544.         { s2++;
  545.           off++;
  546.           len--;
  547.           x++;
  548.         }
  549.         /*}}}  */
  550.        else
  551.         /*{{{  print old text and the speciell handled char*/
  552.         { *s2='\0';
  553.           oputs(s1);
  554.           *s2=c;
  555.           switch (lg)
  556.            { unsigned char ohx[max_dsp];
  557.              unsigned char *xp;
  558.  
  559.              case tab_dsp:
  560.               /*{{{  print as tabs*/
  561.               { do
  562.                  { oputc(' ');
  563.                    off++;
  564.                    len--;
  565.                    x++;
  566.                    if (x==limit) limit=chg_highlight_type(limit,m2);
  567.                  }
  568.                 while (off%dsp.tab_size && len);
  569.                 break;
  570.               }
  571.               /*}}}  */
  572.              case ictrl_dsp:
  573.              case mark_dsp:
  574.               /*{{{  print as ctrl*/
  575.               { if (dsp.ctrl_add)
  576.                    invers();
  577.                 else
  578.                  { oputc(CTRL_MARK);
  579.                    off++;
  580.                    len--;
  581.                    x++;
  582.                    if (x==limit) limit=chg_highlight_type(limit,m2);
  583.                  }
  584.                 if (len)
  585.                  { if (hz&&c==(unsigned char)'~')
  586.                       oputc(HZ_TILDE);
  587.                    else if (c==127)
  588.                       oputc('?');
  589.                    else
  590.                       oputc(ctrl_decode[c]);
  591.                    len--;
  592.                    off++;
  593.                    x++;
  594.                    if (x==limit) limit=chg_highlight_type(limit,m2);
  595.                  }
  596.                 else
  597.                    s2--;
  598.                 if (dsp.ctrl_add)
  599.                    noinvers();
  600.                 break;
  601.               }
  602.               /*}}}  */
  603.              case hex_dsp:
  604.               /*{{{  gen hex*/
  605.                 ohx[1]=hex_digits[(unsigned)c>>4];
  606.                 ohx[2]=hex_digits[(unsigned)c&15];
  607.                 ohx[3]='\0';
  608.                 goto do_numb_dsp;
  609.               /*}}}  */
  610.              case dec_dsp:
  611.               /*{{{  gen decimal*/
  612.                 ohx[1]=DECIMAL_MARK;
  613.                 ohx[2]=hex_digits[(unsigned)c/100];
  614.                 ohx[3]=hex_digits[((unsigned)c/10)%10];
  615.                 ohx[4]=hex_digits[(unsigned)c%10];
  616.                 ohx[5]='\0';
  617.                 goto do_numb_dsp;
  618.               /*}}}  */
  619.              default:
  620.               /*{{{  error*/
  621.                 ori_assert(False,"incorrect dsp-base");
  622.               /*}}}  */
  623.              case oct_dsp:
  624.               /*{{{  gen octal*/
  625.                 ohx[1]=hex_digits[(unsigned char)c>>6];
  626.                 ohx[2]=hex_digits[((unsigned char)c>>3)&7];
  627.                 ohx[3]=hex_digits[(unsigned char)c&7];
  628.                 ohx[4]='\0';
  629.                 goto do_numb_dsp;
  630.               /*}}}  */
  631.              do_numb_dsp:
  632.               /*{{{  prt number*/
  633.                 ohx[0]=NUMB_MARK;
  634.                 /*{{{  print all chars of number*/
  635.                 for (xp=ohx;(c = *xp);xp++)
  636.                    if (len)
  637.                     { oputc(c);
  638.                       off++;
  639.                       len--;
  640.                       x++;
  641.                       if (x==limit)
  642.                          limit=chg_highlight_type(limit,m2);
  643.                     }
  644.                    else
  645.                     { s2--;
  646.                       break;
  647.                     }
  648.                 /*}}}  */
  649.                 break;
  650.               /*}}}  */
  651.            }
  652.           s1= ++s2;
  653.         }
  654.         /*}}}  */
  655.      }
  656.    }
  657.    /*}}}  */
  658.   if (*s1)
  659.    /*{{{  print missing part of line*/
  660.      if (*s2)
  661.       /*{{{  poke 0 into the text and print*/
  662.       { c= *s2;
  663.         *s2='\0';
  664.         oputs(s1);
  665.         *s2=c;
  666.       }
  667.       /*}}}  */
  668.      else
  669.         oputs(s1);
  670.    /*}}}  */
  671.   ori_assert(len>=0,"prt_highlight len crash");
  672.   if (mark && !len)
  673.    /*{{{  maybe put overflow mark*/
  674.    { x++;
  675.      while (*s2==' ' || *s2=='\t') s2++;
  676.      prtendwin(*s2?eoln_str:' ');
  677.    }
  678.    /*}}}  */
  679.   highlight(False,False);
  680.  
  681.   return(x);        /* number of printed characters */
  682. }
  683. /*}}}  */
  684. /*{{{  prt_bin_text*/
  685. public int prt_bin_text(int off,int len,boolean mark,unsigned char *s)
  686. {
  687.   return(prt_highlight_bin_text((LINELEN+2)*max_dsp,(LINELEN+3)*max_dsp,off,len,mark,s));
  688. }
  689. /*}}}  */
  690. /*{{{  move_prt_clreol*/
  691. public void move_prt_clreol(int y,int x,int off,int len,boolean mark,
  692.                           unsigned char *s)
  693. { move_cursor_to(y+bd.scr.off.h,x+bd.scr.off.w);
  694.   x+=prt_bin_text(off,len,mark,s);
  695.   if (x<bd.scr.txt_size.w) clrbuffline(y,x);
  696. }
  697. /*}}}  */
  698. /*{{{  write_dsp_line*/
  699. public void write_dsp_line(element const * const ptr,int level)
  700. {
  701.   if (!scr_off)
  702.    { int m1,m2,off,gap,s_off,x;
  703.      unsigned char *wrt_ptr;
  704.  
  705.      copyin(print_buffer, ptr, False);
  706.      /*{{{  set positions for higlight region*/
  707.      switch (get_highlight(*ptr))
  708.       { case no_highlight:
  709.            m2=(LINELEN+3)*max_dsp;
  710.            m1=(LINELEN+2)*max_dsp;
  711.            break;
  712.         case full_highlight:
  713.            m1=0;
  714.            m2=(LINELEN+2)*max_dsp;
  715.            break;
  716.         case c_f_highlight:
  717.         case m_f_highlight:
  718.            m1=bd.e.makefold_indent;
  719.            m2=(LINELEN+2)*max_dsp;
  720.            break;
  721.         case f_m_highlight:
  722.            m1=0;
  723.            m2=bd.e.makefold_indent+1;
  724.            break;
  725.         case c_m_highlight:
  726.            if (bd.e.makefold_indent<bd.scr.cursor.w)
  727.             { m1=bd.e.makefold_indent;
  728.               m2=bd.scr.cursor.w;
  729.             }
  730.            else
  731.             { m2=bd.e.makefold_indent+1;
  732.               m1=bd.scr.cursor.w-1;
  733.             }
  734.            break;
  735.       }
  736.      /*}}}  */
  737.      /*{{{  handle offsets for full shifting screen*/
  738.      gap=0;
  739.      if ((s_off=bd.scr.full_shift_w))
  740.       { off=scr2txt(bd.f.enter_spaces,s_off+1,print_buffer);
  741.         ori_assert(off>0,"wrt-dsp-line: screen-shift without text-shift");
  742.         if (ustrlen(print_buffer)>off)
  743.          { gap=txt2scr(bd.f.enter_spaces,off,print_buffer)-s_off-1;
  744.            wrt_ptr=print_buffer+off;
  745.          }
  746.         else
  747.            wrt_ptr=(unsigned char*)empty_text;
  748.       }
  749.      else
  750.       { off=0;
  751.         wrt_ptr=print_buffer;
  752.       }
  753.      ori_assert(gap>=0,"wrt-dsp-line: invalid gap size");
  754.      /*}}}  */
  755.      move_cursor_to(level+bd.scr.off.h,1+bd.scr.off.w);
  756.      /*{{{  print leading gap for incomplete chars, init no of printd chars*/
  757.      x=0;
  758.      if (gap)
  759.       { if (soln_str)
  760.          { oputc(soln_str);x=1; }
  761.         while (x<gap)
  762.          { x++;
  763.            oputc(' ');
  764.          }
  765.       }
  766.      /*}}}  */
  767.      /*{{{  print text*/
  768.      x+=prt_highlight_bin_text
  769.          ( m1-off,
  770.            m2-off,
  771.            bd.f.enter_spaces+s_off+gap,
  772.            bd.scr.txt_size.w-1-gap,
  773.            True,
  774.            wrt_ptr
  775.          );
  776.      /*}}}  */
  777.      /*{{{  maybe clear rest of line*/
  778.      if (x<bd.scr.txt_size.w)
  779.         clrbuffline(level,x+1);
  780.      /*}}}  */
  781.      /*{{{  maybe mark left-shift*/
  782.      if (off && soln_str && !gap)
  783.       { move_cursor_to(level+bd.scr.off.h,1+bd.scr.off.w);
  784.         oputc(soln_str);
  785.       }
  786.      /*}}}  */
  787.    }
  788. }
  789. /*}}}  */
  790.  
  791. /*{{{  forward: restore_element*/
  792. public void restore_element(int close_line);
  793. /*}}}  */
  794.  
  795. /*{{{  title_op*/
  796. /*{{{  statusline print data*/
  797. /*{{{  mode braces*/
  798. #define MODE_BEGIN "("
  799. #define MODE_END ") "
  800. /*}}}  */
  801. /*{{{  buffer id/change*/
  802. #define stat_buff " %s%s%c "
  803. #define no_char ' '
  804. #define buff_txt (unsigned char*)": "
  805. #define chg_char '*'
  806. /*}}}  */
  807. /*{{{  version string*/
  808. #define s_version (unsigned char*)" " MAJOR_VERSION "." MINOR_VERSION "." REVISION DEBUG_FEATURE " " MODE_BEGIN
  809. /*}}}  */
  810. /*{{{  window modes*/
  811. #ifdef WINDOW_TITLE_CHANGE
  812. #  ifdef DIREDT
  813. #     define full_win_stat " " MODE_BEGIN "%s%c%s" MODE_END
  814. #  endif
  815. #  define win_stat         " " MODE_BEGIN "%s" MODE_END
  816. #  define no_win_stat      " - "
  817. #endif
  818. /*}}}  */
  819. private unsigned char const d_e_tag[]=DV_TAG;
  820. /*}}}  */
  821. /*{{{  pathcut*/
  822. /*{{{  comment*/
  823. /*
  824.    pathcut: input  char **name
  825.                    (adress of a pointer to filename)
  826.             output int
  827.                    number of cut chars
  828.             sideeffect:
  829.                    if there is a '/'( not at start of the filename), then
  830.                    *name is set to the text behind '/'
  831. */
  832. /*}}}  */
  833. private boolean pathcut(unsigned char **name)
  834. {
  835.   unsigned char *s= *name;
  836.  
  837.   if (*s==PATH_C)
  838.      s++;
  839.   while (*s && *s!=PATH_C)
  840.      s++;
  841.   if (*s)
  842.    { *name=s;
  843.      return(True);
  844.    }
  845.   return(False);
  846. }
  847. /*}}}  */
  848. /*{{{  p_modes*/
  849. /*{{{  p_mode*/
  850. private void p_mode(unsigned char *s,unsigned char const * const m)
  851. {
  852.   if (*m)
  853.    { s+=ustrlen(s);
  854.      *s++=comma;
  855.      ustrcpy(s,m);
  856.    }
  857. }
  858. /*}}}  */
  859.  
  860. private void p_modes(unsigned char *r,boolean sh)
  861. {
  862.   /*{{{  view*/
  863.   if (bd.m.read_only)
  864.      p_mode(r,(unsigned char*)(sh?sVIEW_TAG:VIEW_TAG));
  865.   /*}}}  */
  866.   /*{{{  dirview*/
  867.   if (bd.m.dir_edit)
  868.      p_mode(r,sh?(unsigned char*)sDV_TAG:d_e_tag);
  869.   /*}}}  */
  870. # ifdef REGEXP
  871.    /*{{{  regexp*/
  872.      if (reg_type!=no_reg)
  873.         p_mode
  874.          ( r,
  875.            (unsigned char*)((reg_type==basic_reg)
  876.                               ? (sh?sBREGEXP_TAG:BREGEXP_TAG)
  877.                               : (sh?sXREGEXP_TAG:XREGEXP_TAG)
  878.            )
  879.          );
  880.    /*}}}  */
  881. # endif
  882.   /*{{{  defmac*/
  883.   if (defining_macro)
  884.      p_mode(r,(unsigned char*)(sh?sDM_TAG:DM_TAG));
  885.   /*}}}  */
  886.   /*{{{  folding*/
  887.   if (bd.m.select_mode==fold_selection || bd.m.select_mode==unmark_fold_selection)
  888.      p_mode(r,(unsigned char*)(sh?sFOLD_TAG:FOLD_TAG));
  889.   /*}}}  */
  890.   /*{{{  over*/
  891.   if (bd.m.overwrite)
  892.      p_mode(r,(unsigned char*)(sh?sOVER_TAG:OVER_TAG));
  893.   /*}}}  */
  894.   /*{{{  auto*/
  895.   if (auto_save)
  896.      p_mode(r,(unsigned char*)(sh?sAUTO_TAG:AUTO_TAG));
  897.   /*}}}  */
  898.   /*{{{  nopar*/
  899.   if (bd.e.fold_in)
  900.      p_mode(r,(unsigned char*)(sh?sNOPAR_TAG:NOPAR_TAG));
  901.   /*}}}  */
  902.   /*{{{  hash*/
  903.   if (bd.m.hash_shift)
  904.      p_mode(r,(unsigned char*)H_SHIFT_TAG);
  905.   /*}}}  */
  906.   /*{{{  append user modes*/
  907.   { int i;
  908.     unsigned char **um;
  909.  
  910.     for
  911.      ( i=MODE_COUNT-1,um=u_modes+(sh?(MODE_COUNT-1):(2*MODE_COUNT-1))
  912.      ; i>=0
  913.      ; i--,um--
  914.      )
  915.        if (um_active[i])
  916.         { p_mode(r,*um);
  917.           if (n_modes[i])
  918.              ustrcat(r,i_to_ua(n_modes[i]));
  919.         }
  920.   }
  921.   /*}}}  */
  922.   ustrcat(r,(unsigned char*)MODE_END);
  923.   /*{{{  maybe w_name*/
  924.   if (w_name)
  925.    { ustrcat(r,w_name);
  926.      ustrcat(r,one_space);
  927.    }
  928.   /*}}}  */
  929. }
  930. /*}}}  */
  931. #ifdef WINDOW_TITLE_CHANGE
  932.    public unsigned char statline[BUFFERLEN+1];
  933. #endif
  934.  
  935. public int title_op(TITLE_OP op)
  936. {
  937.   /*{{{  variables*/
  938.   static boolean title_changed=True;
  939.   enum dsp_size old_numb_mode;
  940.   /*}}}  */
  941.  
  942.   old_numb_mode=dsp.norm;
  943.   dsp.norm=norm_dsp;
  944.   switch(op)
  945.    {
  946.      /*{{{  LINE_NO*/
  947.      case LINE_NO:
  948.         break;
  949.      /*}}}  */
  950.      /*{{{  SMALLTITLE,UPDTITLE,PRTTITLE,WINTITLE*/
  951.      case UPDTITLE:
  952.         if (!title_changed)
  953.            break;
  954.      case PRTTITLE:
  955.      case SMALLTITLE:
  956.         if (!scr_off && !var_notitle && !dirty)
  957. #     ifdef WINDOW_TITLE_CHANGE
  958.      case WINTITLE:
  959. #     endif
  960.          /*{{{  do the print*/
  961.          {
  962.            /*{{{  variables*/
  963.            unsigned char filename[_POSIX_PATH_MAX+1];
  964. #           ifndef WINDOW_TITLE_CHANGE
  965.               unsigned char statline[LINELEN+1];
  966. #           endif
  967.            unsigned char *fn_start;
  968.            int max;
  969.            int time_len=0;
  970.            boolean to_long;
  971.            msgtyp old_last;
  972.            /*}}}  */
  973.  
  974.            old_last=last_message;
  975.            /*{{{  get filename*/
  976.            if (bd.f.real_tail == bd.f.real_head)
  977.              *filename = '\0';
  978.            else
  979.              ustrcpy(filename,get_data(bd.f.real_tail));
  980.            /*}}}  */
  981. #         ifdef WINDOW_TITLE_CHANGE
  982.            if (op==WINTITLE)
  983.             /*{{{  buildt title for window*/
  984.             { max=WIN_TITLE_LENGTH(screen.w);
  985.               ustrcpy(statline,origami_name);
  986.               /*{{{  modes*/
  987.               { unsigned char *bn;
  988.  
  989.                 bn=(buff_used<=1)?0:i_to_ua(buff_used);
  990.                 ustrcat
  991.                  ( statline,
  992.                    get_msg
  993.                     ( MSG_ARG_FORMAT,
  994. #                ifdef DIREDT
  995.                         (bn && bd.m.dir_edit)   ? full_win_stat :
  996. #                endif
  997.                         (bn
  998. #                ifdef DIREDT
  999.                             ||  bd.m.dir_edit
  1000. #                endif
  1001.                                               ) ? win_stat :
  1002.                                                   no_win_stat,
  1003. #                ifdef DIREDT
  1004.                         bd.m.dir_edit ? d_e_tag :
  1005. #                endif
  1006.                                                  bn,
  1007.                       comma,
  1008.                       bn
  1009.                     )
  1010.                  );
  1011.                 if (w_name)
  1012.                  { ustrcat(statline,w_name);
  1013.                    ustrcat(statline,one_space);
  1014.                  }
  1015.               }
  1016.               /*}}}  */
  1017.             }
  1018.             /*}}}  */
  1019.            else
  1020. #         endif
  1021.             /*{{{  data for origami's title line*/
  1022.             { max=bd.scr.win.w-(bd.scr.bold_stat?(2*sg):0);
  1023.               /*{{{  buffer id and chg*/
  1024.               ustrcpy
  1025.                ( statline,
  1026.                  get_msg
  1027.                   ( MSG_ARG_FORMAT,
  1028.                     stat_buff,
  1029.                     ((buff_used>1)?i_to_ua(bd.scr.list_no):empty_text),
  1030.                     ((buff_used>1)?buff_txt:empty_text),
  1031.                     (bd.m.file_changed_status?chg_char:no_char)
  1032.                   )
  1033.                );
  1034.               /*}}}  */
  1035.               /*{{{  get statusline data*/
  1036.               { unsigned char *user_c_string;
  1037.  
  1038.                 if (op!=SMALLTITLE)
  1039.                  { max-=(time_len=strlen(time_str));
  1040.                    /*{{{  additional data*/
  1041.                    ustrcat(statline,origami_name);
  1042.                    ustrcat(statline,s_version);
  1043.                    title_debug(statline);
  1044.                    /*{{{  get correct language-mark, fn_start at end of the current string*/
  1045.                    ustrcat(statline,dialects[bd.m.dialect.typ].name);
  1046.                    fn_start=statline;
  1047.                    while (*fn_start) fn_start++;
  1048.                    if (bd.m.dialect.typ == F_C_USER)
  1049.                     /*{{{  append user-comments*/
  1050.                     { *fn_start++=' ';
  1051.                       user_c_string=fn_start;
  1052.                       ustrcpy(fn_start,dialects[F_C_USER].txt.start);
  1053.                       ustrcat(fn_start,one_space);
  1054.                       ustrcat(fn_start,dialects[F_C_USER].txt.end);
  1055.                       while (*fn_start) fn_start++;
  1056.                       if
  1057.                        (    (  dialects[F_C_USER].lg.start
  1058.                              + dialects[F_C_USER].lg.end
  1059.                             )
  1060.                          <= SHORT_F_C_LENGTH
  1061.                        )
  1062.                          user_c_string=0;
  1063.                     }
  1064.                     /*}}}  */
  1065.                    else
  1066.                       user_c_string=0;
  1067.                    *fn_start='\0';
  1068.                    /*}}}  */
  1069.                    /*{{{  modes at end of line*/
  1070.                    p_modes(fn_start,False);
  1071.                    /*}}}  */
  1072.                    /*}}}  */
  1073.                  }
  1074.                 else
  1075.                  /*{{{  fn_start to end of string!*/
  1076.                    fn_start=statline+ustrlen(statline);
  1077.                  /*}}}  */
  1078.                 /*{{{  position*/
  1079.                 if (xy_show)
  1080.                  { if (!bd.S.y_pos)
  1081.                       bd.S.y_pos=line_no(bd.f.current,bd.f.real_head);
  1082.                    ori_assert(bd.scr.cur_shift_w>=0 && bd.scr.cur_shift_w<=LINELEN*max_dsp,"shift-check");
  1083.                    ustrcat
  1084.                     ( fn_start,
  1085.                       get_msg
  1086.                        ( (bd.scr.cur_shift_w>0)?M_XYS_LONG:M_XY_LONG,
  1087.                          bd.S.y_pos,
  1088.                          bd.S.last_x_pos=bd.scr.cursor.w+bd.f.enter_spaces,
  1089.                          bd.scr.cur_shift_w
  1090.                        )
  1091.                     );
  1092.                    ustrcat(fn_start,one_space);
  1093.                  }
  1094.                 /*}}}  */
  1095.                 if (ustrlen(filename)+ustrlen(statline)>max)
  1096.                  /*{{{  try short version and full pathname*/
  1097.                  { if (op!=SMALLTITLE)
  1098.                     {
  1099.                       /*{{{  maybe short user comment*/
  1100.                       if (user_c_string)
  1101.                        { int i;
  1102.                          unsigned char *s,*t;
  1103.  
  1104.                          t=user_c_string;
  1105.                          /*{{{  copy start*/
  1106.                          for
  1107.                           ( i=SHORT_F_C_LENGTH/2,
  1108.                             s=dialects[F_C_USER].txt.start
  1109.                           ; *s && i
  1110.                           ; i--,*t++ = *s++
  1111.                           );
  1112.                          /*}}}  */
  1113.                          if (*s) *t++=eoln_str;
  1114.                          *t++=' ';
  1115.                          /*{{{  copy end*/
  1116.                          for
  1117.                           ( i=SHORT_F_C_LENGTH/2,
  1118.                             s=dialects[F_C_USER].txt.end
  1119.                           ; *s && i
  1120.                           ; i--,*t++ = *s++
  1121.                           );
  1122.                          /*}}}  */
  1123.                          if (*s) *t++=eoln_str;
  1124.                          *t='\0';
  1125.                          fn_start=t;
  1126.                        }
  1127.                       /*}}}  */
  1128.                       /*{{{  modes*/
  1129.                       *fn_start='\0';
  1130.                       p_modes(fn_start,True);
  1131.                       /*}}}  */
  1132.                     }
  1133.                    else
  1134.                       *fn_start='\0';
  1135.                    /*{{{  position*/
  1136.                    ori_assert(bd.scr.cur_shift_w<=LINELEN*max_dsp,"shift-check");
  1137.                    if (xy_show)
  1138.                     { ustrcat
  1139.                        ( fn_start,
  1140.                          get_msg
  1141.                           ( (bd.scr.cur_shift_w>0)?M_XYS_SHORT:M_XY_SHORT,
  1142.                             bd.S.y_pos,
  1143.                             bd.S.last_x_pos,
  1144.                             bd.scr.cur_shift_w
  1145.                           )
  1146.                        );
  1147.                       ustrcat(fn_start,one_space);
  1148.                     }
  1149.                    /*}}}  */
  1150.                  }
  1151.                  /*}}}  */
  1152.               }
  1153.               /*}}}  */
  1154.             }
  1155.             /*}}}  */
  1156.            /*{{{  fn_start to end of string!*/
  1157.            fn_start=statline+ustrlen(statline);
  1158.            /*}}}  */
  1159.            ustrcpy(fn_start,filename);
  1160.            if (ustrlen(statline)>max)
  1161.             /*{{{  cut filename*/
  1162.             { unsigned char *fn;
  1163.               boolean loop;
  1164.               boolean cut;
  1165.  
  1166.               for (fn=filename,loop=True,cut=False;loop;)
  1167.                {
  1168.                  /*{{{  cat filename to statusline*/
  1169.                  *fn_start='\0';
  1170.                  if (cut)
  1171.                     ustrcpy(fn_start,M_CUT_PATH);
  1172.                  ustrcat(fn_start,fn);
  1173.                  /*}}}  */
  1174.                  if ((to_long=(ustrlen(statline)>max)) && pathcut(&fn))
  1175.                     cut=True;
  1176.                  else
  1177.                     loop=False;
  1178.                }
  1179.             }
  1180.             /*}}}  */
  1181.            else
  1182.               to_long=False;
  1183.            /*{{{  maybe handle time*/
  1184.            if (time_len)
  1185.             { ustrcat(fn_start,(unsigned char*)time_str);
  1186.               to_long=(ustrlen(statline)>(max+=time_len));
  1187.             }
  1188.            /*}}}  */
  1189.            /*{{{  handle end of line*/
  1190.            if (to_long)
  1191.             { statline[max-1]=eoln_str;
  1192.               statline[max]='\0';
  1193.             }
  1194.            else
  1195. #           ifdef WINDOW_TITLE_CHANGE
  1196.                 if (op!=WINTITLE)
  1197. #           endif
  1198.             { int l;
  1199.  
  1200.               l=ustrlen(statline);
  1201.               spaces(statline+l,max-l);
  1202.             }
  1203.            /*}}}  */
  1204. #          ifdef WINDOW_TITLE_CHANGE
  1205.               if (op==WINTITLE)
  1206.                  break;
  1207. #          endif
  1208.            /*{{{  print the line*/
  1209.            move_cursor_to(bd.scr.win.h+bd.scr.off.h,1+bd.scr.off.w);
  1210.            if (bd.scr.bold_stat) highlight(True,True);
  1211.            prt_bin_text(0,max,False,statline);
  1212.            if (bd.scr.bold_stat) highlight(False,True);
  1213.            /*}}}  */
  1214.            title_changed=False;
  1215.            last_message=old_last;
  1216.          }
  1217.          /*}}}  */
  1218.         break;
  1219.      /*}}}  */
  1220.      /*{{{  CHGXY*/
  1221.      case CHGXY:
  1222.         bd.S.last_x_pos=0;
  1223.         bd.S.y_pos=0;
  1224.      chg_line:
  1225.         if (xy_show) goto chg_title;
  1226.         break;
  1227.      /*}}}  */
  1228.      /*{{{  CHGTITLE*/
  1229.      case CHGTITLE:
  1230.      chg_title:
  1231.        title_changed=True;
  1232.        break;
  1233.      /*}}}  */
  1234.      /*{{{  CHGX*/
  1235.      case CHGX:
  1236.         if (bd.S.last_x_pos!=bd.scr.cursor.w+bd.f.enter_spaces)
  1237.            goto chg_line;
  1238.         break;
  1239.      /*}}}  */
  1240.      /*{{{  INCY*/
  1241.      case INCY:
  1242.         if (bd.S.y_pos) bd.S.y_pos++;
  1243.         goto chg_line;
  1244.      /*}}}  */
  1245.      /*{{{  DECY*/
  1246.      case DECY:
  1247.         if (bd.S.y_pos) bd.S.y_pos--;
  1248.         goto chg_line;
  1249.      /*}}}  */
  1250.    }
  1251.   dsp.norm=old_numb_mode;
  1252.  
  1253.   return(bd.S.y_pos);
  1254. }
  1255. /*}}}  */
  1256.  
  1257. /*{{{  restore_area_line*/
  1258. private void restore_area_line(int const y)
  1259. { int dsp;
  1260.  
  1261.   if (scr_off || !area_used) return;
  1262.   /*{{{  print area_line*/
  1263.   if ((dsp=y+area_line.h)<message_line)
  1264.    { moveclreol(dsp,1);
  1265.      move_cursor_to(dsp,1);
  1266.      { boolean wsg=!var_notitle && (dsp==(message_line-1));
  1267.  
  1268.        if (wsg) highlight(True,True);
  1269.        prt_bin_text(0,area_line.w-(wsg?sg+sg:0),False,area_lines[y]);
  1270.        if (wsg) highlight(False,True);
  1271.      }
  1272.    }
  1273.   /*}}}  */
  1274. }
  1275. /*}}}  */
  1276. /*{{{  store_area_line*/
  1277. private void store_area_line(unsigned char const * const x,int const no)
  1278. {
  1279.   /*{{{  maybe free old data*/
  1280.   if (area_lines[no]!=empty_text)
  1281.      paket_free(area_lines[no]);
  1282.   /*}}}  */
  1283.   /*{{{  store data*/
  1284.   area_lines[no]=(unsigned char*)empty_text;
  1285.   if (*x)
  1286.      if ((area_lines[no]=ori_malloc(ustrlen(x)+1)))
  1287.         ustrcpy(area_lines[no],x);
  1288.      else
  1289.         warn_message(M_NO_MALLOC);
  1290.   /*}}}  */
  1291. }
  1292. /*}}}  */
  1293. /*{{{  restore_area*/
  1294. public void restore_area(void)
  1295. { int y;
  1296.  
  1297.   for (y=area_line.h;y<message_line;restore_area_line(y++-area_line.h));
  1298. }
  1299. /*}}}  */
  1300. /*{{{  set_area*/
  1301. public void set_area (int new_size)
  1302. { int i;
  1303.  
  1304.   /*{{{  remove old area*/
  1305.   if (area_used)
  1306.    { for
  1307.       ( i=area_used;
  1308.         i--;
  1309.         store_area_line(empty_text,i)
  1310.       );
  1311.      paket_free(area_lines);
  1312.    }
  1313.   /*}}}  */
  1314.   /*{{{  get new area-size*/
  1315.   i=area_used=new_size;
  1316.   if (screen.h-4<area_used || area_used<=0)
  1317.    { area_used=0;
  1318.      if (i)
  1319.         msg_message(M_NO_AREA);
  1320.    }
  1321.   /*}}}  */
  1322.   /*{{{  get place for new arealines*/
  1323.   if (!(area_lines=ori_malloc(area_used*sizeof(char*))))
  1324.      exit_origami(r_mem_full,M_NO_MEMORY);
  1325.   /*}}}  */
  1326.   /*{{{  clear the buffers*/
  1327.   while (i--)
  1328.      area_lines[i]=(unsigned char*)empty_text;
  1329.   /*}}}  */
  1330. }
  1331. /*}}}  */
  1332. /*{{{  write_area*/
  1333. void write_area (int x,int y,unsigned char const *pr)
  1334. {
  1335.   /*{{{  variables*/
  1336.   int ex;
  1337.   unsigned char *p=print_buffer;
  1338.   /*}}}  */
  1339.  
  1340.   /*{{{  get position to write to*/
  1341.   ex= --x;
  1342.   --y;
  1343.   /*}}}  */
  1344.   /*{{{  check position*/
  1345.   if (!area_used || x<0 || y<0 || y>=area_used)
  1346.    { msg_message(M_NO_AREA);
  1347.      return;
  1348.    }
  1349.   /*}}}  */
  1350.   /*{{{  copy line to printbuffer and set p to correct x-position for writing*/
  1351.   ustrcpy(print_buffer,area_lines[y]);
  1352.   while (x--) if (*p) p++; else { *p=' ';*(++p)='\0'; }
  1353.   /*}}}  */
  1354.   /*{{{  copy string to correct position*/
  1355.   ustrcpy(p,pr);
  1356.   /*}}}  */
  1357.   /*{{{  restore rest of old line*/
  1358.   ex+=ustrlen(p);
  1359.   if (ex<ustrlen(area_lines[y]))
  1360.      ustrcat(p,area_lines[y]+ex);
  1361.   /*}}}  */
  1362.   /*{{{  move new line to storage and show it*/
  1363.   store_area_line(print_buffer,y);
  1364.   restore_area_line(y);
  1365.   /*}}}  */
  1366. }
  1367. /*}}}  */
  1368.  
  1369. /*{{{  restore*/
  1370. public void restore(int from)
  1371. {
  1372.   element *p=bd.scr.start;
  1373.   int h;
  1374.  
  1375.   for (h = 1; h <= bd.scr.end_level; h++)
  1376.    {
  1377.      /*{{{  display if under from*/
  1378.      if (h >= from)
  1379.         write_dsp_line(p, h);
  1380.      /*}}}  */
  1381.      p = p->next;
  1382.    }
  1383.   for (h=bd.scr.end_level+1;h<=bd.scr.txt_size.h;h++)
  1384.      clrbuffline(h,1);
  1385.   title_op(CHGTITLE);
  1386. }
  1387. /*}}}  */
  1388. /*{{{  restore_to_end*/
  1389. public void restore_to_end(int from)
  1390. {  /*if select_on then set select separately*/
  1391.   bd.scr.end = bd.f.current;
  1392.   bd.scr.end_level = bd.scr.cursor.h;
  1393.   while (bd.scr.end_level < bd.scr.txt_size.h && bd.scr.end != bd.f.tail)
  1394.    { bd.scr.end_level++;
  1395.      bd.scr.end = bd.scr.end->next;
  1396.    }
  1397.   restore(from);
  1398. }
  1399. /*}}}  */
  1400. /*{{{  restore_element*/
  1401. public void restore_element(int close_line)
  1402. {  /*if select_on then set select separately*/
  1403.   int level, dist_to_end;
  1404.   int dist_to_start;
  1405.  
  1406.   dist_to_start = to_start((int)(bd.scr.txt_size.h - 1));
  1407.   dist_to_end = to_bottom((int)(bd.scr.txt_size.h - 2));
  1408.   if ((bd.scr.cursor.h=close_line)<2)
  1409.      bd.scr.cursor.h=2;
  1410.   else if (close_line>=bd.scr.txt_size.h)
  1411.      bd.scr.cursor.h=bd.scr.txt_size.h-1;
  1412.   if (dist_to_start<bd.scr.cursor.h)
  1413.      bd.scr.cursor.h = dist_to_start;
  1414.   while
  1415.    (    bd.scr.cursor.h+dist_to_end < bd.scr.txt_size.h
  1416.      && dist_to_start > bd.scr.cursor.h
  1417.    ) bd.scr.cursor.h++;
  1418.   for (level=bd.scr.cursor.h-1,bd.scr.start=bd.f.current;level>0;level--)
  1419.      bd.scr.start = bd.scr.start->prec;
  1420.   restore_to_end(1);
  1421. }
  1422. /*}}}  */
  1423. /*{{{  restore_or_restore_to_end*/
  1424. public void restore_or_restore_to_end(void)
  1425. { element *p;
  1426.  
  1427.   if (bd.scr.start != bd.f.head->next) {
  1428.     restore_element(bd.scr.txt_size.h/2);
  1429.     return;
  1430.   }
  1431.   p = bd.f.head->next;
  1432.   bd.scr.cursor.h = 1;
  1433.   while (p != bd.f.current) {
  1434.     bd.scr.cursor.h++;
  1435.     p = p->next;
  1436.   }
  1437.   restore_to_end(bd.scr.cursor.h);
  1438. }
  1439. /*}}}  */
  1440. /*{{{  restore_shift*/
  1441. public boolean restore_shift(int off)
  1442. {
  1443.   if
  1444.    (    ( bd.m.full_shift && bd.scr.full_shift_w!=off )
  1445.      || (!bd.m.full_shift && bd.scr.full_shift_w )
  1446.    )
  1447.    { bd.scr.full_shift_w=bd.m.full_shift?off:0;
  1448.      copyout(cur_dsp_line,bd.f.current);
  1449.      restore(1);
  1450.      return(True);
  1451.    }
  1452.   return(False);
  1453. }
  1454. /*}}}  */
  1455.  
  1456. /*{{{  up_a_bit*/
  1457. public void up_a_bit(int from)
  1458. { int dirty_line=0;
  1459.  
  1460.   if (from!=bd.scr.txt_size.h)
  1461.      if
  1462.       /*{{{  cannot scroll*/
  1463.       ( B_scroll_region
  1464.          ( from+bd.scr.off.h,1+bd.scr.off.w,
  1465.            bd.scr.txt_size.h+bd.scr.off.h,bd.scr.off.w+bd.scr.txt_size.w,
  1466.            True
  1467.          )
  1468.       )
  1469.       /*}}}  */
  1470.       /*{{{  simulate by add/delete line or redraw*/
  1471.       { move_cursor_to(from+bd.scr.off.h,1);
  1472.         if (bd.scr.win.w!=screen.w||DelLine(1))
  1473.            dirty_line=from;
  1474.         else
  1475.          { move_cursor_to(bd.scr.txt_size.h+bd.scr.off.h,1);
  1476.            if (insLine(1))
  1477.               dirty_line=bd.scr.txt_size.h;
  1478.          }
  1479.         if (dirty_line)
  1480.            restore_to_end(dirty_line);
  1481.       }
  1482.       /*}}}  */
  1483.      else if (bd.scr.win.w+bd.scr.off.w!=screen.w)
  1484.       /*{{{  print right margin of buffer again*/
  1485.       { move_cursor_to(bd.scr.txt_size.h+bd.scr.off.h,bd.scr.txt_size.w+bd.scr.off.w);
  1486.         prtendwin(' ');
  1487.       }
  1488.       /*}}}  */
  1489.   move_cursor_to(from+bd.scr.off.h,1+bd.scr.off.w);
  1490. }
  1491. /*}}}  */
  1492. /*{{{  down_a_bit*/
  1493. public void down_a_bit(int from)
  1494. { int dirty_line=0;
  1495.  
  1496.   if (from!=bd.scr.txt_size.h)
  1497.      if
  1498.       /*{{{  cannot scroll*/
  1499.       ( B_scroll_region
  1500.          ( from+bd.scr.off.h,1+bd.scr.off.w,
  1501.            bd.scr.txt_size.h+bd.scr.off.h,bd.scr.off.w+bd.scr.txt_size.w,
  1502.            False
  1503.          )
  1504.       )
  1505.       /*}}}  */
  1506.       /*{{{  simulate by add/delete line or redraw*/
  1507.       { move_cursor_to(from+bd.scr.off.h,1);
  1508.         if (bd.scr.win.w!=screen.w||insLine(1))
  1509.            dirty_line=from;
  1510.         else
  1511.          { move_cursor_to(bd.scr.txt_size.h+1+bd.scr.off.h,1);
  1512.            if (DelLine(1))
  1513.             { dirty_line=bd.scr.txt_size.h+1;
  1514.               message(empty_text);
  1515.             }
  1516.          }
  1517.         if (dirty_line)
  1518.            restore_to_end(dirty_line);
  1519.       }
  1520.       /*}}}  */
  1521.    move_cursor_to(from+bd.scr.off.h,1+bd.scr.off.w);
  1522. }
  1523. /*}}}  */
  1524. /*{{{  whole_screen_up*/
  1525. public void whole_screen_up(void)
  1526. {
  1527.   if (bd.scr.start == bd.f.tail) return;
  1528.   bd.scr.start = bd.scr.start->next;
  1529.   bd.scr.cursor.h--;
  1530.   up_a_bit(1);
  1531.   if (bd.scr.end != bd.f.tail) {
  1532.     bd.scr.end = bd.scr.end->next;
  1533.     write_dsp_line(bd.scr.end, bd.scr.txt_size.h);
  1534.   } else
  1535.     bd.scr.end_level--;
  1536. }
  1537. /*}}}  */
  1538. /*{{{  whole_screen_down*/
  1539. public void whole_screen_down(void)
  1540. {
  1541.   if (bd.scr.start == bd.f.head->next) return;
  1542.   bd.scr.start = bd.scr.start->prec;
  1543.   bd.scr.cursor.h++;
  1544.   if (bd.scr.end_level == bd.scr.txt_size.h)
  1545.     bd.scr.end = bd.scr.end->prec;
  1546.   else
  1547.     bd.scr.end_level++;
  1548.   down_a_bit(1);
  1549.   write_dsp_line(bd.scr.start,1);
  1550. }
  1551. /*}}}  */
  1552.  
  1553. /*{{{  upd_highlight*/
  1554. public boolean upd_highlight(element *hd, element *tl, boolean full)
  1555. {
  1556.   element *m1,*m2;
  1557.  
  1558.   if (!allow_text_so)
  1559.      return(False);
  1560.   /*{{{  handle delay for screen-off*/
  1561.   if (scr_off)
  1562.    { bd.m.upd_sel_delayed=True;
  1563.      return(False);
  1564.    }
  1565.   else
  1566.      bd.m.upd_sel_delayed=False;
  1567.   /*}}}  */
  1568.   /*{{{  set pointers to selections*/
  1569.   if (bd.m.select_mode==no_selection)
  1570.      if (bd.m.last_no_sel)
  1571.         return(False);
  1572.      else
  1573.       { m1=m2=0;
  1574.         bd.m.last_no_sel=True;
  1575.       }
  1576.   else
  1577.    { m1=bd.f.select_ptr;
  1578.      m2=bd.f.current;
  1579.      bd.m.last_no_sel=False;
  1580.    }
  1581.   /*}}}  */
  1582.   for (;;)
  1583.    /*{{{  do one loop*/
  1584.    {
  1585.      /*{{{  variables*/
  1586.      highlight_typ msingle,mstart,min,mend;
  1587.      element *p;
  1588.      boolean inside;
  1589.      boolean use_next;
  1590.      int match;
  1591.      /*}}}  */
  1592.  
  1593.      /*{{{  set highlight types and move-mode*/
  1594.      use_next=False;
  1595.      switch (bd.m.select_mode)
  1596.       { case fold_selection:
  1597.            use_next=True;
  1598.            mstart=min=m_f_highlight;
  1599.            msingle=mend=no_highlight;
  1600.            break;
  1601.         case lim_pseudo_fold_selection:
  1602.            use_next=True;
  1603.         case pseudo_fold_selection:
  1604.            msingle=mstart=min=m_f_highlight;
  1605.            mend=no_highlight;
  1606.            break;
  1607.         case lim_reg_selection:
  1608.            use_next=True;
  1609.         case reg_selection:
  1610.            msingle=c_m_highlight;
  1611.            mstart=c_f_highlight;
  1612.            min=full_highlight;
  1613.            mend=f_m_highlight;
  1614.            break;
  1615.         case lim_block_selection:
  1616.            use_next=True;
  1617.         case block_selection:
  1618.            msingle=mstart=min=mend=c_m_highlight;
  1619.            break;
  1620.         case no_selection:
  1621.         case nodrawn_selection:
  1622.         case unmark_fold_selection:
  1623.         case lim_nodrawn_selection:
  1624.         default:
  1625.            msingle=mstart=min=mend=no_highlight;
  1626.            break;
  1627.       }
  1628.      /*}}}  */
  1629.      /*{{{  set highlight flags in range*/
  1630.      /*{{{  maybe shift hd/tl, set initial value for inside*/
  1631.      inside=False;
  1632.      if (!full)
  1633.       { if (hd!=bd.f.real_head)
  1634.          { hd=hd->prec;
  1635.            inside=get_highlight(*hd);
  1636.          }
  1637.         if (tl!=bd.f.real_tail) tl=tl->next;
  1638.       }
  1639.      /*}}}  */
  1640.      for (p=hd,match=0;;)
  1641.       { highlight_typ h;
  1642.  
  1643.         /*{{{  maybe change m1<->m2, if m2 < m1*/
  1644.         if (!inside && p==m2) { m2=m1;m1=p; }
  1645.         /*}}}  */
  1646.         /*{{{  get highlight flag for this line*/
  1647.         if (p==m1)
  1648.          /*{{{  handle start of selection*/
  1649.          { match++;
  1650.            if (p==m2)
  1651.             { match++;
  1652.               h=msingle;
  1653.             }
  1654.            else
  1655.             { inside=True;
  1656.               h=mstart;
  1657.             }
  1658.          }
  1659.          /*}}}  */
  1660.         else if (p==m2)
  1661.          /*{{{  handle end of selection*/
  1662.          { match++;
  1663.            inside=False;
  1664.            h=mend;
  1665.          }
  1666.          /*}}}  */
  1667.         else if (inside)
  1668.            h=min;
  1669.         else
  1670.            h=no_highlight;
  1671.         /*}}}  */
  1672.         /*{{{  set flags*/
  1673.         { linetyp t;
  1674.  
  1675.           t=get_linetyp(*p);
  1676.           set_lflags(*p,t,h);
  1677.         }
  1678.         /*}}}  */
  1679.         if (p==tl)
  1680.            break;
  1681.         if (use_next)
  1682.            p=p->next;
  1683.         else
  1684.            p=move_on(p);
  1685.       }
  1686.      /*}}}  */
  1687.      if (full && bd.m.select_mode!=no_selection && match!=2)
  1688.       { bd.m.select_mode=no_selection;
  1689.         warn_message(get_msg(M_FOLDERR));
  1690.         ocl_msg("highlight crash",0);
  1691.         ori_abort(~SIGINT);
  1692.         /* now loop a second time and reset flags :-) */
  1693.       }
  1694.      else
  1695.         return(True);
  1696.    }
  1697.    /*}}}  */
  1698. }
  1699. /*}}}  */
  1700.